#pragma once

#include "stdafx.h"

#include "Common.h"
#include "ZobristHashes.h"



struct BitBoardCache
{
	uint32 wm;
	uint32 bm;
	uint32 wk;
	uint32 bk;
};

struct BitBoardCache64
{
	uint64 wm;
	uint64 bm;
	uint64 wk;
	uint64 bk;
};


#pragma pack(push, 1)

// master transposition table cache item
struct CacheItem
{
public:

	ZOBRIST_KEY boardKey;			// 8 bytes
	bool bWhite;
	int iValueLower;				// 4 bytes
	int iValueUpper;				// 4 bytes
	int8 iDepth;					// 1 byte
	int8 nestedLevel;				// 1 byte
	uint8 m_hashType; 				// 1 byte
	BitBoardCache bbBestMove;		// 16 bytes
	uint16 dwDummy;					// 2 bytes - alignment
};									// SUM 32 bytes

struct CacheItem64
{
public:

	ZOBRIST_KEY boardKey;			// 8 bytes
	int iValue;						// 4 bytes
	int8 iDepth;					// 1 byte
	uint8 m_hashType; 				// 1 byte
	BitBoardCache64 bbBestMove;		// 32 bytes
	uint16 dwDummy;					// 2 bytes - alignment
};									// SUM 48 bytes


// evaluation cache item
struct EvalCacheItem
{
	ZOBRIST_KEY boardKey;
	int Value;
};

#pragma pack(pop)

// types of cache records
#define hashfVALUE 1
#define hashfALPHA 2
#define hashfBETA  4

// master transpositon table cache
template<typename BB> void Cache_Allocate(SEngineData* ed, long cacheSizeMB);
template<> void Cache_Allocate<BitBoard>(SEngineData* ed, long cacheSizeMB);
template<> void Cache_Allocate<BitBoard64>(SEngineData* ed, long cacheSizeMB);

template<typename BB> void Cache_Free(SEngineData* ed);
template<> void Cache_Free<BitBoard>(SEngineData* ed);
template<> void Cache_Free<BitBoard64>(SEngineData* ed);

template<typename BB> void Cache_Clear(SEngineData *ed);
template<> void Cache_Clear<BitBoard>(SEngineData *ed);
template<> void Cache_Clear<BitBoard64>(SEngineData *ed);

template<typename BB>
bool Cache_Lookup(SEngineData* ed, ZOBRIST_KEY key, int depth, int nestedLevel, uint8& hashType, int& value, int& alpha, int& beta, bool bWhite, BB* bestMove);
template<>
bool Cache_Lookup<BitBoard>(SEngineData* ed, ZOBRIST_KEY key, int depth, int nestedLevel, uint8& hashType, int& value, int& alpha, int& beta, bool bWhite, BitBoard* bestMove);
template<>
bool Cache_Lookup<BitBoard64>(SEngineData* ed, ZOBRIST_KEY key, int depth, int nestedLevel, uint8& hashType, int& value, int& alpha, int& beta, bool bWhite, BitBoard64* bestMove);

template<typename BB>
void Cache_Store(SEngineData* ed, ZOBRIST_KEY key, int depth, int nestedLevel, int value, uint8 hashF, bool bWhite, BB* bestMove);
template<>
void Cache_Store<BitBoard>(SEngineData* ed, ZOBRIST_KEY key, int depth, int nestedLevel, int value, uint8 hashF, bool bWhite, BitBoard* bestMove);
template<>
void Cache_Store<BitBoard64>(SEngineData* ed, ZOBRIST_KEY key, int depth, int nestedLevel, int value, uint8 hashF, bool bWhite, BitBoard64* bestMove);


void FindNearestDumpFile();
void DumpCache(SEngineData* ed);


// evaluation cache
//void EvalCache_Allocate(long itemCount);
//void EvalCache_Free();
//bool EvalCache_Lookup(ZOBRIST_KEY key, int* pValue);
//void EvalCache_Store(ZOBRIST_KEY key, int value);
